// src/common/utils/paginate.ts
import {
  Model,
  Document,
  FilterQuery,
  QueryOptions,
  PipelineStage,
} from 'mongoose';

/** 分页参数选项 */
export interface IPaginationOptions {
  page?: number; // 页码，默认1
  pageSize?: number; // 每页条数，默认10
}

/** 分页元数据（包含分页统计信息） */
export interface IPaginationMeta {
  totalItems: number; // 总数据条数
  itemCount: number; // 当前页数据条数
  itemsPerPage: number; // 每页显示条数
  totalPages: number; // 总页数
  currentPage: number; // 当前页码
}

/** 分页结果统一格式 */
export interface Pagination<T> {
  items: T[]; // 当前页数据列表
  meta: IPaginationMeta; // 分页统计信息
}

// 默认分页配置
const DEFAULT_PAGE = 1;
const DEFAULT_PAGE_SIZE = 10;
const MAX_PAGE_SIZE = 10000; // 限制最大每页条数

/** 解析并处理分页参数（确保参数合法性） */
const resolvePagination = (options: IPaginationOptions) => {
  const page = Math.max(options.page || DEFAULT_PAGE, 1); // 页码最小为1
  const pageSize = Math.max(
    Math.min(options.pageSize || DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE),
    1, // 每页条数最小为1
  );
  const skip = (page - 1) * pageSize; // 计算跳过的条数
  return { page, pageSize, skip };
};

/** 生成标准分页结果 */
const buildPaginationResult = <T>(
  items: T[],
  totalItems: number,
  page: number,
  pageSize: number,
): Pagination<T> => ({
  items,
  meta: {
    totalItems,
    itemCount: items.length,
    itemsPerPage: pageSize,
    totalPages: Math.ceil(totalItems / pageSize),
    currentPage: page,
  },
});

/**
 * 基础分页查询（适用于简单条件查询）
 * @param model Mongoose 数据模型
 * @param options 分页参数
 * @param filter 查询条件（可选）
 * @param queryOptions 额外查询配置（排序、投影等，可选）
 */
export async function paginate<T extends Document>(
  model: Model<T>,
  options: IPaginationOptions,
  filter: FilterQuery<T> = {},
  queryOptions: QueryOptions = {},
): Promise<Pagination<T>> {
  const { page, pageSize, skip } = resolvePagination(options);

  // 并行执行：查询数据 + 统计总数（提升性能）
  const [items, totalItems] = await Promise.all([
    model.find(filter, null, { ...queryOptions, skip, limit: pageSize }).exec(),
    model.countDocuments(filter).exec(),
  ]);

  return buildPaginationResult(items, totalItems, page, pageSize);
}

/**
 * 聚合管道分页查询（适用于复杂查询：联表、统计等）
 * @param model Mongoose 数据模型
 * @param pipeline 聚合管道数组
 * @param options 分页参数
 */
export async function paginateAggregate<T extends Document>(
  model: Model<T>,
  pipeline: PipelineStage[],
  options: IPaginationOptions,
): Promise<Pagination<T>> {
  const { page, pageSize, skip } = resolvePagination(options);

  // 并行执行：聚合查询（带分页） + 统计总数
  const [items, countResult] = await Promise.all([
    model
      .aggregate<T>([...pipeline, { $skip: skip }, { $limit: pageSize }])
      .exec(),
    model.aggregate([...pipeline, { $count: 'total' }]).exec(),
  ]);

  const totalItems = countResult[0]?.total || 0;
  return buildPaginationResult(items, totalItems, page, pageSize);
}
